﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;

namespace InteractSMSRetriever
{
   // PC Connectivity API headers
   using PCCSErrors;
   using CONADefinitions;
   using CONADeviceManagement;
   using CAContentAccess;
   using PCCSTypeDefinitions;

   public partial class Form1 : Form
   {
      private const int m_iIconPhoneIndex = 0;
      private const int m_iIconNoPhoneIndex = 1;
      private const int m_iIconSMSMessagesIndex = 4;
      private const int m_iIconSMSIndex = 5;
      private const string errorMsg = "Error\nCode: ";
      private const int waitTime = 5000;

      // Device manager handle
      private int m_hDMHandle = 0;
      private CONADefinitions.DeviceNotifyCallbackDelegate pDeviceCallBack;
      private CAContentAccess.DAContentAccessDefinitions.CANotifyCallbackDelegate pCANotifyCallBack;
      private CAContentAccess.DAContentAccessDefinitions.CAOperationCallbackDelegate pCAOperationCallback;
      private int m_hSMS = 0;
      private int m_hCurrentConnection = 0;
      private string m_strCurrentSMSSerialNumber = "";
      private IntPtr m_pSMSBuffer = IntPtr.Zero;

      private CAFolderInfo inboxFolderInfo;
      private PhoneDetails phoneDetail;
      private ArrayList retrievedMsgs;
      private bool isRunning;
      private DBConnection dbConn;

      private struct CAFolderInfo
      {
         public int iFolderId;
         public int iOptions;
         public string strName;
         public string strPath;
         public bool iSubfolderCount;
         public bool bIsChild;
      }

      private struct CAItemID
      {
         public int iFolderId;
         public int iTemporaryID;
         public byte[] abUID;
         public int iStatus;
      }

      private struct ProgressItem
      {
         public ListViewItem listItem;
         public CAItemID retrievedMessage;
         public bool clearList;
      }

      public Form1()
      {
         InitializeComponent();

         retrievedMsgs = new ArrayList();
      }

      private void Form1_Load(object sender, EventArgs e)
      {
         pCANotifyCallBack = CANotifyCallBack;
         pCAOperationCallback = CAOperationCallback;
         // Initialize Device Management APi
         int iResult = CONADeviceManagement.DMAPI_Initialize(CONADeviceManagement.DMAPI_VERSION_32, 0);
         // Initialize Data Access API
         iResult = DAContentAccess.CAAPI_Initialize(DAContentAccess.CAAPI_VERSION_30, 0);

         // Get Device management handle
         iResult = CONADeviceManagement.CONAOpenDM(ref m_hDMHandle);

         // Register device notification callback function
         pDeviceCallBack = DeviceNotifyCallback;
         iResult = CONADeviceManagement.CONARegisterNotifyCallback(m_hDMHandle, CONADefinitions.API_REGISTER, pDeviceCallBack);

         //RefreshList();
         isRunning = true;
         runButton.Text = "Stop";
         runToolStripMenuItem.Text = "Stop";
         if (!backgroundWorker.IsBusy)
         {
            backgroundWorker.RunWorkerAsync();
         }
      }

      private void RefreshList()
      {
         CloseSMSConnection();
         //smsListView.Items.Clear();

         if (m_hDMHandle == 0)
         {
            return;
         }

         int iRet = CONADeviceManagement.CONARefreshDeviceList(m_hDMHandle, 0);

         CONADefinitions.CONAPI_DEVICE[] pDevices;
         int iDeviceCount = 0;

         iRet = CONADeviceManagement.CONAGetDeviceCount(m_hDMHandle, ref iDeviceCount);

         if (iRet == PCCSErrors.CONA_OK & iDeviceCount > 0)
         {
            pDevices = null;
            pDevices = new CONADefinitions.CONAPI_DEVICE[iDeviceCount];

            // Allocate memory for buffer
            IntPtr buffer = Marshal.AllocHGlobal(iDeviceCount * Marshal.SizeOf(typeof(CONADefinitions.CONAPI_DEVICE)));

            // Get list of currently connected devices
            iRet = CONADeviceManagement.CONAGetDevices(m_hDMHandle, ref iDeviceCount, buffer);
            if (iRet == PCCSErrors.CONA_OK)
            {
               //retrievedMsgs = new ArrayList();
               // Add each device to the tree view
               for (int iDeviceIndex = 0; iDeviceIndex < iDeviceCount; iDeviceIndex++)
               {
                  // Calculate beginning of CONAPI_DEVICE structure of item 'i'
                  Int64 iPtr = buffer.ToInt64() + iDeviceIndex * Marshal.SizeOf(typeof(CONADefinitions.CONAPI_DEVICE));
                  // Convert integer to pointer
                  IntPtr ptr = new IntPtr(iPtr);
                  // Copy data from buffer
                  pDevices[iDeviceIndex] = (CONADefinitions.CONAPI_DEVICE)Marshal.PtrToStructure(ptr, typeof(CONADefinitions.CONAPI_DEVICE));
                  // Insert phone item in tree view
                  phoneDetail = new PhoneDetails();
                  phoneDetail.Name = pDevices[iDeviceIndex].pstrFriendlyName;
                  phoneDetail.PhoneIndex = m_iIconPhoneIndex;
                  phoneDetail.SerialNumber = pDevices[iDeviceIndex].pstrSerialNumber;
                  GetSMSFolders(phoneDetail.SerialNumber);
                  GetSMSMessages(phoneDetail.SerialNumber);
               }

               // Free memory allocated by CONAGetDevices
               CONADeviceManagement.CONAFreeDeviceStructure(iDeviceCount, buffer);
               if (iRet != PCCSErrors.CONA_OK)
               {
                  ShowErrorMessage("CONAFreeDeviceStructure", iRet);
               }
            }
            Marshal.FreeHGlobal(buffer);
         }
         if (iRet == PCCSErrors.CONA_OK & iDeviceCount == 0)
         {
            // NO PHONE
            ListViewItem newItem = new ListViewItem();
            newItem.Text = "No phones connected";
            ProgressItem progress = new ProgressItem();
            progress.clearList = true;
            progress.listItem = newItem;
            progress.retrievedMessage = new CAItemID();
            //smsListView.Items.Add(newItem);
            backgroundWorker.ReportProgress(0, progress);
         }
      }

      private void GetSMSFolders(string strSerialNumber)
      {
         // Check PIM connection to SMS folders and open it if needed
         int iRet = CheckSMSConnection(strSerialNumber);
         if (iRet == PCCSErrors.CONA_OK)
         {
            // Get SMS folder info
            CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo;
            folderInfo = new CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO();
            folderInfo.iSize = Marshal.SizeOf(folderInfo);
            IntPtr bufItem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO)));
            Marshal.StructureToPtr(folderInfo, bufItem, true);

            iRet = DAContentAccess.CAGetFolderInfo(m_hSMS, bufItem);
            if (iRet == PCCSErrors.CONA_OK)
            {
               folderInfo = (CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO)Marshal.PtrToStructure(bufItem, typeof(CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO));
               FindFolder(folderInfo);
            }
            else
            {
               ShowErrorMessage("CAGetFolderInfo", iRet);
            }

            int iResult = DAContentAccess.CAFreeFolderInfoStructure(bufItem);
            if (iResult != PCCSErrors.CONA_OK)
            {
               ShowErrorMessage("CAFreeFolderInfoStructure", iResult);
            }

            Marshal.FreeHGlobal(bufItem);
         }
      }

      private int CheckSMSConnection(string strSerialNumber)
      {
         int iRet = PCCSErrors.CONA_OK;
         if (m_strCurrentSMSSerialNumber != strSerialNumber)
         {
            // Device has changed, close previous connection
            CloseSMSConnection();
            m_strCurrentSMSSerialNumber = strSerialNumber;
         }

         if (m_hSMS == 0)
         {
            // No PIM connection, open it
            IntPtr pstrSerialNumber = Marshal.StringToCoTaskMemUni(strSerialNumber);
            int iMedia = CONADefinitions.API_MEDIA_ALL;
            int iTarget = CADataDefinitions.CA_TARGET_SMS_MESSAGES;

            iRet = DAContentAccess.DAOpenCA(pstrSerialNumber, ref iMedia, iTarget, ref m_hSMS);
            if (iRet != PCCSErrors.CONA_OK & iRet != PCCSErrors.ECONA_NOT_SUPPORTED_DEVICE)
            {
               ShowErrorMessage("DAOpenCA", iRet);
            }
            Marshal.FreeCoTaskMem(pstrSerialNumber);

            // Register device notification callback function
            if (m_hSMS != 0)
            {
               int iResult = DAContentAccess.CARegisterNotifyCallback(m_hSMS, PCCSTypeDefinitions.API_REGISTER, pCANotifyCallBack);
               if (iResult != PCCSErrors.CONA_OK)
               {
                  ShowErrorMessage("CARegisterNotifyCallback", iResult);
               }
            }
         }
         return iRet;
      }

      private int CloseSMSConnection()
      {
         int iRet = PCCSErrors.CONA_OK;
         if (m_hSMS != 0)
         {
            // Unregister CallBack
            int iResult = DAContentAccess.CARegisterNotifyCallback(m_hSMS, PCCSTypeDefinitions.API_UNREGISTER, pCANotifyCallBack);
            if (iResult != PCCSErrors.CONA_OK)
            {
               ShowErrorMessage("CONARegisterNotifyCallback", iResult);
            }

            // Close PIM connection
            iRet = DAContentAccess.DACloseCA(m_hSMS);
            if (iRet != PCCSErrors.CONA_OK)
            {
               ShowErrorMessage("DACloseCA", iRet);
            }

            m_hSMS = 0;
         }
         return iRet;
      }

      private void FindFolder(CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo)
      {
         string strFolderName = folderInfo.pstrName;

         for (int i = 0; i < folderInfo.iSubFolderCount; i++)
         {
            // Recursive call for adding subfolders.
            CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO subFolderInfo = new CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO();
            subFolderInfo.iSize = Marshal.SizeOf(typeof(CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO));

            // Calculate beginning of CONAPI_DEVICE structure of item 'i'
            Int64 iPtr = folderInfo.pSubFolders.ToInt64() + i * Marshal.SizeOf(typeof(CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO));
            // Convert integer to pointer
            IntPtr ptr = new IntPtr(iPtr);
            // Copy data from buffer
            subFolderInfo = (CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO)Marshal.PtrToStructure(ptr, typeof(CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO));
            string path = folderInfo.pstrPath;
            string folder = subFolderInfo.pstrName;
            //if (folder.Contains("inbox"))
            if (folder.Contains("inbox"))
            {
               inboxFolderInfo = MapCFIToCAFolderInfo(subFolderInfo);
            }

            FindFolder(subFolderInfo);
         }
      }

      private void GetSMSMessages(string strSerialNumber)
      {
         // Check PIM connection to SMS folders and open it if needed
         int iRet = CheckSMSConnection(strSerialNumber);
         if (iRet == PCCSErrors.CONA_OK)
         {
            // Set SMS folder target path
            DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo = MapCAFolderInfoToCFI(inboxFolderInfo);
            if (folderInfo.iFolderId == 0)
            {
               return;
               // SMS root folder
            }
            // Read all the SMS item IDs from the connected device 
            CAContentAccess.DAContentAccessDefinitions.CA_ID_LIST caIDList = new DAContentAccessDefinitions.CA_ID_LIST();
            caIDList.iSize = Marshal.SizeOf(caIDList);
            IntPtr buf = Marshal.AllocHGlobal(Marshal.SizeOf(caIDList));
            Marshal.StructureToPtr(caIDList, buf, true);

            iRet = DAContentAccess.CAGetIDList(m_hSMS, folderInfo.iFolderId, 0, buf);
            // With messages, ECONA_NOT_FOUND is "OK" return value in some situations
            // (item exists, but phone/library is not ready yet)
            if ((iRet != PCCSErrors.CONA_OK) & (iRet != PCCSErrors.ECONA_NOT_FOUND))
            {
               ShowErrorMessage("CAGetIDList", iRet);
            }

            caIDList = (CAContentAccess.DAContentAccessDefinitions.CA_ID_LIST)Marshal.PtrToStructure(buf, typeof(CAContentAccess.DAContentAccessDefinitions.CA_ID_LIST));
            int hOperHandle = 0;

            iRet = DAContentAccess.CABeginOperation(m_hSMS, 0, ref hOperHandle);
            if (iRet != PCCSErrors.CONA_OK)
            {
               ShowErrorMessage("CABeginOperation", iRet);
            }

            bool clearList = true;
            if (caIDList.iUIDCount == 0)
            {
               ProgressItem progress = new ProgressItem();
               progress.listItem = null;
               progress.retrievedMessage = new CAItemID();
               progress.clearList = true;
               backgroundWorker.ReportProgress(0, progress);
            }

            Console.WriteLine(caIDList.iUIDCount);
            for (int k = 0; k < caIDList.iUIDCount; k++)
            {
               Console.WriteLine("test");
               // Read SMS item from the connected device
               DAContentAccessDefinitions.CA_ITEM_ID UID = GetUidFromBuffer(k, caIDList.pUIDs);

               IntPtr bufId = Marshal.AllocHGlobal(Marshal.SizeOf(UID));
               Marshal.StructureToPtr(UID, bufId, true);
               CAContentAccess.CADataDefinitions.CA_DATA_MSG dataSMS = new CADataDefinitions.CA_DATA_MSG();
               dataSMS.iSize = Marshal.SizeOf(dataSMS);
               dataSMS.bAddressCount = 0;
               dataSMS.iDataLength = 0;
               dataSMS.iInfoField = 0;
               dataSMS.pAddress = IntPtr.Zero;
               dataSMS.pbData = IntPtr.Zero;
               GetEmptyPIMDate(ref dataSMS.messageDate);
               IntPtr bufData = Marshal.AllocHGlobal(dataSMS.iSize);
               Marshal.StructureToPtr(dataSMS, bufData, true);

               iRet = DAContentAccess.CAReadItem(hOperHandle, bufId, DAContentAccessDefinitions.CA_OPTION_USE_CACHE, CADataDefinitions.CA_DATA_FORMAT_STRUCT, bufData);
               if (iRet == PCCSErrors.CONA_OK)
               {
                  dataSMS = (CAContentAccess.CADataDefinitions.CA_DATA_MSG)Marshal.PtrToStructure(bufData, typeof(CAContentAccess.CADataDefinitions.CA_DATA_MSG));
                  if (dataSMS.iDataLength > 0)
                  {
                     if ((CADataDefinitions.CA_GET_DATA_FORMAT(dataSMS.iInfoField)) == CADataDefinitions.CA_DATA_FORMAT_UNICODE)
                     {
                        if (!IntPtr.Zero.Equals(dataSMS.pbData))
                        {
                           // Insert SMS message item in tree view
                           System.Windows.Forms.TreeNode itemZ = new System.Windows.Forms.TreeNode();
                           string strData = Marshal.PtrToStringUni(dataSMS.pbData, dataSMS.iDataLength / 2);
                           ListViewItem newItem = new ListViewItem();
                           newItem.Text = strData;
                           //newItem.Text = Convert.ToBase64String(MapUIDToCAItemID(UID).abUID) + strData;
                           //newItem.Text = MapUIDToCAItemID(UID).iTemporaryID.ToString() + "=" + strData;
                           newItem.Tag = MapUIDToCAItemID(UID);
                           //retrievedMsgs.Add(MapUIDToCAItemID(UID));
                           //smsListView.Items.Add(newItem);
                           ProgressItem progress = new ProgressItem();
                           progress.listItem = newItem;
                           progress.retrievedMessage = MapUIDToCAItemID(UID);
                           progress.clearList = clearList;
                           backgroundWorker.ReportProgress(0, progress);
                           clearList = false;
                        }
                        else
                        {
                           // No data, GMS or other kind of message?
                        }
                     }
                     else
                     {
                        // Message in data format
                     }
                  }
               }
               else
               {
                  ShowErrorMessage("CAReadItem", iRet);
                  break; // TODO: might not be correct. Was : Exit For
                  // Reading failed, quit loop.
               }

               // Free memory allocated by DA API
               iRet = DAContentAccess.CAFreeItemData(m_hSMS, CADataDefinitions.CA_DATA_FORMAT_STRUCT, bufData);
               if (iRet != PCCSErrors.CONA_OK)
               {
                  ShowErrorMessage("DAFreeItemData", iRet);
               }

               Marshal.FreeHGlobal(bufData);
               Marshal.FreeHGlobal(bufId);
            }

            iRet = DAContentAccess.CAEndOperation(hOperHandle);
            if (iRet != PCCSErrors.CONA_OK)
            {
               ShowErrorMessage("CAEndOperation", iRet);
            }

            iRet = DAContentAccess.CAFreeIdListStructure(buf);
            if (iRet != PCCSErrors.CONA_OK)
            {
               ShowErrorMessage("CAFreeIdListStructure", iRet);
            }

            Marshal.FreeHGlobal(buf);
         }
      }

      public int DeviceNotifyCallback(
            int iStatus,
            [MarshalAs(UnmanagedType.LPWStr)] string pstrSerialNumber)
      {
         return PCCSErrors.CONA_OK;
      }

      public int CANotifyCallBack(int hCAHandle, int iReason, int iParam, IntPtr pItemID)
      {
         string strStatus = "";

         if (iReason == CAContentAccess.DAContentAccessDefinitions.CA_REASON_ENUMERATING)
         {
            strStatus = "CANotifyCallBack: CA_REASON_ENUMERATING";
         }
         else if (iReason == CAContentAccess.DAContentAccessDefinitions.CA_REASON_ITEM_ADDED)
         {
            strStatus = "CANotifyCallBack: CA_REASON_ITEM_ADDED";
         }
         else if (iReason == CAContentAccess.DAContentAccessDefinitions.CA_REASON_ITEM_DELETED)
         {
            strStatus = "CANotifyCallBack: CA_REASON_ITEM_DELETED";
         }
         else if (iReason == CAContentAccess.DAContentAccessDefinitions.CA_REASON_ITEM_UPDATED)
         {
            strStatus = "CANotifyCallBack: CA_REASON_ITEM_UPDATED";
         }
         else if (iReason == CAContentAccess.DAContentAccessDefinitions.CA_REASON_ITEM_MOVED)
         {
            strStatus = "CANotifyCallBack: CA_REASON_ITEM_MOVED";
         }
         else if (iReason == CAContentAccess.DAContentAccessDefinitions.CA_REASON_ITEM_REPLACED)
         {
            strStatus = "CANotifyCallBack: CA_REASON_ITEM_REPLACED";
         }
         else if (iReason == CAContentAccess.DAContentAccessDefinitions.CA_REASON_CONNECTION_LOST)
         {
            strStatus = "CANotifyCallBack: CA_REASON_CONNECTION_LOST";
         }
         else if (iReason == CAContentAccess.DAContentAccessDefinitions.CA_REASON_MSG_DELIVERY)
         {
            strStatus = "CANotifyCallBack: CA_REASON_MSG_DELIVERY";
         }
         
         Console.WriteLine(strStatus);

         return PCCSErrors.CONA_OK;
      }

      public int CAOperationCallback(int hOperHandle, int iOperation, int iCurrent, int iTotalAmount, int iStatus, IntPtr pItemID)
      {
         string strStatus = String.Format("CAOperationCallback: Operation({0}), progress({0}), total({0}), status({0})", iOperation, iCurrent, iTotalAmount, iStatus);
         Console.WriteLine(strStatus);
         return PCCSErrors.CONA_OK;
      }

      private CAFolderInfo MapCFIToCAFolderInfo(CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO CFI)
      {
         CAFolderInfo functionReturnValue = new CAFolderInfo();
         functionReturnValue.iFolderId = CFI.iFolderId;
         functionReturnValue.iOptions = CFI.iOptions;
         functionReturnValue.strName = CFI.pstrName;
         functionReturnValue.strPath = CFI.pstrPath;
         functionReturnValue.iSubfolderCount = CFI.iSubFolderCount != 0;
         functionReturnValue.bIsChild = (CFI.pParent != IntPtr.Zero);
         return functionReturnValue;
      }

      private CAItemID MapUIDToCAItemID(CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID UID)
      {
         CAItemID functionReturnValue = new CAItemID();
         functionReturnValue.iFolderId = UID.iFolderId;
         functionReturnValue.iTemporaryID = UID.iTemporaryID;
         functionReturnValue.iStatus = UID.iStatus;
         if (UID.iUidLen > 0)
         {
            functionReturnValue.abUID = new byte[UID.iUidLen];
            Marshal.Copy(UID.pbUid, functionReturnValue.abUID, 0, UID.iUidLen);
         }
         else
         {
            functionReturnValue.abUID = null;
         }
         return functionReturnValue;
      }

      private CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO MapCAFolderInfoToCFI(CAFolderInfo caFolder)
      {
         CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO functionReturnValue = new CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO();
         functionReturnValue.iSize = Marshal.SizeOf(typeof(CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO));
         functionReturnValue.iFolderId = caFolder.iFolderId;
         functionReturnValue.iOptions = caFolder.iOptions;
         functionReturnValue.pstrName = caFolder.strName;
         functionReturnValue.pstrPath = caFolder.strPath;
         functionReturnValue.iSubFolderCount = 0;
         functionReturnValue.pSubFolders = IntPtr.Zero;
         functionReturnValue.pParent = IntPtr.Zero;
         return functionReturnValue;
      }

      private CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID GetUidFromBuffer(int iIndex, IntPtr pUIds)
      {
         // Calculate beginning of item 'iIndex'
         Int64 iPtr = pUIds.ToInt64() + (iIndex * Marshal.SizeOf(typeof(CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID)));
         // Convert integer to pointer
         IntPtr ptr = new IntPtr(iPtr);
         // Copy data from buffer
         return (CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID)Marshal.PtrToStructure(ptr, typeof(CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID));
      }

      private CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID MapCAItemIDToUID(CAItemID caID)
      {
         CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID functionReturnValue = new CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID();
         functionReturnValue.iSize = Marshal.SizeOf(typeof(CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID));
         functionReturnValue.iFolderId = caID.iFolderId;
         functionReturnValue.iTemporaryID = caID.iTemporaryID;
         functionReturnValue.iStatus = caID.iStatus;
         if (caID.abUID == null)
         {
            functionReturnValue.iUidLen = 0;
            functionReturnValue.pbUid = IntPtr.Zero;
         }
         else
         {
            int iSize = caID.abUID.GetUpperBound(0) - caID.abUID.GetLowerBound(0) + 1;
            functionReturnValue.iUidLen = iSize;
            functionReturnValue.pbUid = Marshal.AllocHGlobal(iSize);
            Marshal.Copy(caID.abUID, 0, functionReturnValue.pbUid, iSize);
         }
         return functionReturnValue;
      }

      private void GetEmptyPIMDate(ref CAContentAccess.CADataDefinitions.CA_DATA_DATE pimDate)
      {
         pimDate.iSize = Marshal.SizeOf(pimDate);
         pimDate.bDay = 0;
         pimDate.lBias = 0;
         pimDate.bHour = 0;
         pimDate.bMinute = 0;
         pimDate.bMonth = 0;
         pimDate.bSecond = 0;
         pimDate.lTimeZoneBias = 0;
         pimDate.wYear = 0;
      }

      private void FreeUIDMappingMemory(CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID UID)
      {
         Marshal.FreeHGlobal(UID.pbUid);
         UID.pbUid = IntPtr.Zero;
      }

      private void refreshButton_Click(object sender, EventArgs e)
      {
         RefreshList();
      }

      private void deleteButton_Click(object sender, EventArgs e)
      {
         DeleteMessage();
      }

      private void DeleteMessage()
      {
         string strSerialNumber = GetCurrentDevice();
         if (strSerialNumber.Length == 0)
         {
            return;
         }
         CheckSMSConnection(strSerialNumber);
         // SMS folder selected
         m_hCurrentConnection = m_hSMS;

         Console.WriteLine("retrievedMsgs.Count = " + retrievedMsgs.Count);
         if (retrievedMsgs.Count > 0)
         {
            /*DialogResult result = MessageBox.Show(
               "Are you sure you want to delete all retrieved messages?",
               "Confirm Item Delete", MessageBoxButtons.YesNo,
               MessageBoxIcon.Question);

            if (result == DialogResult.Yes)
            {*/
               for (int i = 0; i < retrievedMsgs.Count; i++)
               {
                  int hOperHandle = 0;
                  int iRet = DAContentAccess.CABeginOperation(m_hCurrentConnection, 0, ref  hOperHandle);
                  if (iRet != PCCSErrors.CONA_OK)
                  {
                     ShowErrorMessage("CABeginOperation", iRet);
                  }
                  // Deletes PIM item from currently connected device
                  CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID UID = new DAContentAccessDefinitions.CA_ITEM_ID();
                  //CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO CFI = new CAContentAccess.DAContentAccessDefinitions.CA_FOLDER_INFO();
                  IntPtr buffer = IntPtr.Zero;

                  if (object.ReferenceEquals(retrievedMsgs[i].GetType(), typeof(CAItemID)))
                  {
                     UID = MapCAItemIDToUID((CAItemID)retrievedMsgs[i]);
                     UID.iSize = Marshal.SizeOf(UID);
                  }

                  buffer = Marshal.AllocHGlobal(Marshal.SizeOf(UID));
                  Marshal.StructureToPtr(UID, buffer, true);

                  iRet = DAContentAccess.CADeleteItem(hOperHandle, buffer, 0);
                  if (iRet == PCCSErrors.CONA_OK)
                  {
                     // Delete item from list view
                     //smsListView.SelectedItems[0].Remove();
                  }
                  else
                  {
                     ShowErrorMessage("DADeleteItem", iRet);
                  }
                  Marshal.FreeHGlobal(buffer);

                  iRet = DAContentAccess.CACommitOperations(hOperHandle, IntPtr.Zero);
                  if (iRet != PCCSErrors.CONA_OK)
                  {
                     ShowErrorMessage("CACommitOperations", iRet);
                  }

                  iRet = DAContentAccess.CAEndOperation(hOperHandle);
                  if (iRet != PCCSErrors.CONA_OK)
                  {
                     ShowErrorMessage("CAEndOperation", iRet);
                  }

                  FreeUIDMappingMemory(UID);
               }
               retrievedMsgs = new ArrayList();
            }
         //}
      }

      private void smsListView_SelectedIndexChanged(object sender, EventArgs e)
      {
         if (smsListView.SelectedItems.Count > 0)
         {
            ListViewItem selectedItem = smsListView.SelectedItems[0];
            //CAContentAccess.DAContentAccessDefinitions.CA_ITEM_ID UID = new DAContentAccessDefinitions.CA_ITEM_ID();
            string strSerialNumber = GetCurrentDevice();
            if (strSerialNumber.Length == 0)
            {
               return;
            }
            CheckSMSConnection(strSerialNumber);
            // SMS folder selected
            m_hCurrentConnection = m_hSMS;
         }
      }

      private string GetCurrentDevice()
      {
         return phoneDetail.SerialNumber;
      }

      private void ShowErrorMessage(string functionName, int errorCode)
      {
         MessageBox.Show(errorMsg + errorCode + " (" + functionName + ")", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
      }

      private void retrieveButton_Click(object sender, EventArgs e)
      {
         RefreshList();
         DeleteMessage();
      }

      private void Form1_Resize(object sender, EventArgs e)
      {
         if (this.WindowState == FormWindowState.Minimized)
         {
            this.Hide();
         }
      }

      private void openToolStripMenuItem_Click(object sender, EventArgs e)
      {
         this.Show();
         this.WindowState = FormWindowState.Normal;
      }

      private void closeToolStripMenuItem_Click(object sender, EventArgs e)
      {
         this.Close();
      }

      private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
      {
         dbConn = new DBConnection();
         dbConn.OnlyOpenConnection();

         int i = 0;
         while (isRunning)
         {
            //MessageBox.Show("running loop " + i);
            if (backgroundWorker.CancellationPending)
            {
               e.Cancel = true;
               break;
            }

            //retrievedMsgs = new ArrayList();
            RefreshList();

            int iDeviceCount = 0;
            CONADeviceManagement.CONAGetDeviceCount(m_hDMHandle, ref iDeviceCount);

            if (iDeviceCount > 0)
            {
               DeleteMessage();
            }

            Thread.Sleep(waitTime);
            i++;
         }

         dbConn.OnlyCloseConnection();
      }

      private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
      {
         ProgressItem newItem = (ProgressItem)e.UserState;

         if (newItem.clearList)
         {
            smsListView.Items.Clear();
            smsListView.Refresh();
         }

         if (newItem.retrievedMessage.abUID != null)
         {
            if (newItem.listItem != null)
            {
               smsListView.Items.Add(newItem.listItem);
               Console.WriteLine(newItem.listItem);

               if (!AlreadyExists(Convert.ToBase64String(newItem.retrievedMessage.abUID)))
               {
                  retrievedMsgs.Add(newItem.retrievedMessage);
                  Console.WriteLine("count: " + retrievedMsgs.Count);
                  Console.WriteLine(Convert.ToBase64String(newItem.retrievedMessage.abUID));
                  ParseAndInsert(newItem.listItem.Text);
               }
            }
         }
      }

      private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
         //MessageBox.Show("Stopping backgroundworker");
         runButton.Text = "Start";
         runButton.Enabled = true;
         runToolStripMenuItem.Text = "Start";
         runToolStripMenuItem.Enabled = true;
      }

      private void ToggleRunButtons()
      {
         if (runButton.Text == "Start")
         {
            if (!backgroundWorker.IsBusy)
            {
               runButton.Text = "Stop";
               runButton.Enabled = false;
               runToolStripMenuItem.Text = "Stop";
               runToolStripMenuItem.Enabled = false;
               isRunning = true;
               backgroundWorker.RunWorkerAsync();
               runButton.Enabled = true;
               runToolStripMenuItem.Enabled = true;
            }
         }
         else
         {
            if (backgroundWorker.IsBusy)
            {
               runButton.Text = "Stopping...";
               runButton.Enabled = false;
               runToolStripMenuItem.Text = "Stopping...";
               runToolStripMenuItem.Enabled = false;
               backgroundWorker.CancelAsync();
            }
            else
            {
               runButton.Text = "Start";
               runButton.Enabled = true;
               runToolStripMenuItem.Text = "Start";
               runToolStripMenuItem.Enabled = true;
               isRunning = false;
            }
         }
      }

      private void runButton_Click(object sender, EventArgs e)
      {
         ToggleRunButtons();
      }

      private void runToolStripMenuItem_Click(object sender, EventArgs e)
      {
         ToggleRunButtons();
      }

      private void ParseAndInsert(string originalMessage)
      {
         //code, pass, qNum, answer |or| code, pass, query
         string[] messageElements = Regex.Split(originalMessage,"\\s+");

         /*int i = 0;
         Console.Write(messageElements[i]);
         for (i = 1; i < messageElements.Length; i++)
         {
            Console.Write(", " + messageElements[i]);
         }
         Console.WriteLine();*/

         if (messageElements.Length > 2)
         {
            int num = 0;
            bool isNum = Int32.TryParse(messageElements[2], out num);
            if (isNum)
            {
               // question
               string code = messageElements[0];
               string pass = messageElements[1];

               string[] newArray = new string[messageElements.Length - 3];
               Array.Copy(messageElements, 3, newArray, 0, messageElements.Length - 3);
               string answer = String.Join(" ", newArray);
               dbConn.InsertSMSMessage(code, pass, answer, true, num);
            }
            else
            {
               // query
               string code = messageElements[0];
               string pass = messageElements[1];
               string[] newArray = new string[messageElements.Length - 2];
               Array.Copy(messageElements, 2, newArray, 0, messageElements.Length - 2);
               string answer = String.Join(" ", newArray);

               dbConn.InsertSMSMessage(code, pass, answer, false, 0);
            }
         }
      }

      private bool AlreadyExists(string convertedString)
      {
         bool exists = false;
         for (int i = 0; i < retrievedMsgs.Count; i++)
         {
            CAItemID temp = (CAItemID) retrievedMsgs[i];
            if (Convert.ToBase64String(temp.abUID) == convertedString)
            {
               exists = true;
               return exists;
            }
         }

         return exists;
      }

      private void Form1_FormClosing(object sender, FormClosingEventArgs e)
      {
         if (backgroundWorker.IsBusy)
         {
            backgroundWorker.CancelAsync();
         }
      }
   }
}
